package cn.echogo.framework.widget;

import android.content.Context;
import android.gesture.Gesture;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.widget.ImageView;

/**
 * 可放大缩小的图
 * 
 */
public class EGScaleImageView extends ImageView {

	private static final String tag = EGScaleImageView.class.getSimpleName();

	private static final int NONE = 0;
	private static final int DRAG = 1;
	private static final int ZOOM = 2;

	private static final float MIN_DIST = 5.0f;
	private static final int FLING_MIN_DISTANCE = 100;
	private static final int FLING_MIN_VELOCITY = 200;

	private Context context;
	private Matrix savedMatrix;
	private Matrix matrix;
	private int mode = NONE;

	private PointF start = new PointF();
	private PointF mid = new PointF();
	private float oldDist = 1f;

	private GestureDetector detector;

	public EGScaleImageView(Context context) {
		super(context);
		this.context = context;
	}

	public EGScaleImageView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.context = context;
	}

	public void setImageResource(int resId) {
		init();
		super.setImageResource(resId);
	}

	public void setImageDrawable(Drawable drawable) {
		init();
		super.setImageDrawable(drawable);
	}

	public void setImageBitmap(Bitmap bm) {
		init();
		super.setImageBitmap(bm);
	}

	private void init() {
		matrix = new Matrix();
		savedMatrix = new Matrix();
		setScaleType(ScaleType.MATRIX);
		detector = new GestureDetector(context, gestureListener);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		detector.onTouchEvent(event);
		switch (event.getAction() & MotionEvent.ACTION_MASK) {
		case MotionEvent.ACTION_DOWN:
			savedMatrix.set(matrix);
			start.set(event.getX(), event.getY());
			mode = DRAG;
			break;
		case MotionEvent.ACTION_POINTER_DOWN:
			oldDist = spacing(event);
			if (oldDist > MIN_DIST) {
				savedMatrix.set(matrix);
				midPoint(mid, event);
				mode = ZOOM;
			}
			break;
		// case MotionEvent.ACTION_MOVE:
		// if (mode == DRAG) {
		// matrix.set(savedMatrix);
		// matrix.postTranslate(event.getX() - start.x, event.getY() - start.y);
		// } else if (mode == ZOOM) {
		// float newDist = spacing(event);
		// if (newDist > MIN_DIST) {
		// matrix.set(savedMatrix);
		// float scale = newDist / oldDist;
		// matrix.postScale(scale, scale, mid.x, mid.y);
		// }
		// }
		// break;
		case MotionEvent.ACTION_UP:
		case MotionEvent.ACTION_POINTER_UP:
			mode = NONE;
			matrix = new Matrix();
			break;
		}
		setImageMatrix(matrix);
		return true;
	}

	/**
	 * （2点触摸时）计算2点之间的距离
	 * 
	 * @param event
	 * @return
	 */
	private float spacing(MotionEvent event) {
		float x = event.getX(0) - event.getX(1);
		float y = event.getY(0) - event.getY(1);
		return FloatMath.sqrt(x * x + y * y);
	}

	private float spacing(float distanceX, float distanceY) {
		return FloatMath.sqrt(distanceX * distanceX + distanceY * distanceY);
	}

	/**
	 * （2点触摸时）计算2点的中点坐标，结果存到point中
	 * 
	 * @param point
	 * @param event
	 */
	private void midPoint(PointF point, MotionEvent event) {
		float x = event.getX(0) + event.getX(1);
		float y = event.getY(0) + event.getY(1);
		point.set(x / 2, y / 2);
	}

	private SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() {

		@Override
		public boolean onDown(MotionEvent event) {
			final int action = event.getAction() & MotionEvent.ACTION_MASK;
			int pointerCount = event.getPointerCount();
			Log.d(tag, "onDown ::: " + action + ", pointer ::: " + pointerCount);
			// switch (action) {
			// case MotionEvent.ACTION_DOWN:
			// mode = DRAG;
			// break;
			// case MotionEvent.ACTION_POINTER_DOWN: //没有这事件
			// oldDist = spacing(event);
			// if (oldDist > MIN_DIST) {
			// midPoint(mid, event);
			// mode = ZOOM;
			// }
			// break;
			// }

			mode = pointerCount > 1 ? ZOOM : DRAG;
			return true;
		}

		@Override
		public boolean onScroll(MotionEvent event1, MotionEvent event2, float distanceX, float distanceY) {
			int pointerCount = event2.getPointerCount();
			Log.d(tag, "onScroll ::: " + ", pointer ::: " + pointerCount);
			if (mode == DRAG) {
				// matrix.set(savedMatrix);
				matrix.postTranslate(-distanceX, -distanceY);
			} else if (mode == ZOOM) {
				float newDist = spacing(event2);
				float oldDist = newDist - spacing(distanceX, distanceY);
				if (newDist > MIN_DIST) {
					// matrix.set(savedMatrix);
					float scale = newDist / oldDist;
					matrix.postScale(scale, scale, mid.x, mid.y);
				}
			}
			return true;
		}

		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
			Log.d(tag, "onFling :::");
			return super.onFling(e1, e2, velocityX, velocityY);
		}

		@Override
		public boolean onDoubleTap(MotionEvent e) {
			Log.d(tag, "onDoubleTap :::");
			return super.onDoubleTap(e);
		}

	};

}
